

if(${CMAKE_HOST_UNIX})
    message(STATUS "You are running on unix systems")
    add_compile_definitions(GF_LINUX)
elseif(${CMAKE_HOST_WIN32})
    message(STATUS "You are running on windows system, Version: ${CMAKE_HOST_SYSTEM_VERSION}")
    add_compile_definitions(GF_WINDOWS)
elseif(${CMAKE_HOST_APPLE})
    message(WARNING "You are running on MACOS, support will coming soon...")
endif()

if(NOT ${CMAKE_BUILD_TYPE})
    set(${CMAKE_BUILD_TYPE} Debug)
endif()

##compiler stuff.
if(MSVC)
    add_definitions(-D_WIN32_WINNT=0x0600 -D_GNU_SOURCE -D_CRT_SECURE_NO_WARNINGS)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /utf-8")
else()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wextra -Wno-implicit-fallthrough -fPIC -march=native")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -Wextra -Wno-implicit-fallthrough -fPIC -march=native")
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
    message(STATUS "You are using GNU compiler")
    add_compile_options("-static-libstdc++")
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
    message(WARNING "Clang compiler settings are not test")
    message(WARNING "Use it at your own risk!")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()

##end of compiler stuff.

if(${CMAKE_BUILD_TYPE} EQUAL "Release")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -O3")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -O3")
    ##decide if we can use avx or sse for compuattion.
endif(${CMAKE_BUILD_TYPE} EQUAL "Release")

##append our own cmake path to cmake module path.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
##add some compiling options.

option(USE_CONAN "Use conan as cpp package manager" ON)
option(USE_GPU "Use gpu when performing computation" ON)
option(USE_CPU "Use CPU as computation power" OFF)
option(SAVE_LOG "Saving logs info during runtime" ON)
option(ALLOW_SUPER_CONFIG "Allow super configuration when dependencies are missing" OFF)
option(WITH_DOCS "Building docs when compilation" ON)

##end of compiling options.

find_package(Eigen3 QUIET)
find_package(GLM QUIET)

set(SKIP_EIGEN 0)
set(SKIP_GLM 0)

if(${Eigen3_FOUND})
    message(STATUS "Eigen Version: ${Eigen3_VERSION}")
    set(SKIP_EIGEN 1)
else()
    message(STATUS "Eigen not found")
    set(SKIP_EIGEN 0)
endif(${Eigen3_FOUND})

if(${GLM_FOUND})
    message(STATUS "GLM Version: ${GLM_VERSION}")
    set(SKIP_GLM 1)
else()
    message(STATUS "GLM not found")
    set(SKIP_GLM 0)
endif(${GLM_FOUND})

if(${USE_CONAN})
    message(STATUS "Conan will be used as CPP package manager")
    list(APPEND CONAN_SUPPORT_PACKAGES "Eigen3" "GLM")
    message(STATUS "Conan packages:")
    foreach(P ${CONAN_SUPPORT_PACKAGES})
        message(STATUS "    ${P}") 
    endforeach(P)

    set(CMAKE_CUSTUM_DIR ${CMAKE_SOURCE_DIR}/ShapeAnalysis/cmake)
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_BINARY_DIR}")
    list(APPEND CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" "${CMAKE_BINARY_DIR}")
    ##todo: remove this setting if it is not required.
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_BINARY_DIR}/ShapeAnalysis")
    list(APPEND CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}" "${CMAKE_BINARY_DIR}/ShapeAnalysis")

    include(${CMAKE_CUSTUM_DIR}/ConanConfig.cmake)
    include(${CMAKE_CUSTUM_DIR}/ConanEigen.cmake)
    include(${CMAKE_CUSTUM_DIR}/ConanGLM.cmake)

    download_conan_file_if_not_exist(${CMAKE_CUSTUM_DIR})

    download_eigen_if_not_exist()
    download_glm_if_not_exist()

    find_package(Eigen3 REQUIRED)
    find_package(glm REQUIRED)
    include_directories(${Eigen3_Eigen_INCLUDE_DIR})    
    include_directories(${glm_INCLUDE_DIR})

else(${USE_CONAN})
    message(STATUS "Conan manager will not be used")
    if(${ALLOW_SUPER_CONFIG})
        ################################################
        # TODO: add super configuration for dependencies.
        ################################################
    else(${ALLOW_SUPER_CONFIG})
        ################################################
        # TODO: handle dependencies missing.
        ################################################      
    endif(${ALLOW_SUPER_CONFIG})  
    
endif(${USE_CONAN})

##find docs-related stuff.
find_package(Doxygen QUIET)

if(${WITH_DOCS})
    if(${Doxygen_FOUND})
        message(STATUS "Doxygen Version: ${DOXYGEN_VERSION}")
        message(STATUS "Docs will be generated using Doxygen")
        add_compile_definitions(GF_DOC)
    else(${Doxygen_FOUND})
        message(WARNING "Doxygen not found")
        if(${ALLOW_SUPER_CONFIG})
            message(STATUS "Doxygen will download and compile from github")
            add_compile_definitions(GF_DOC)
        else(${ALLOW_SUPER_CONFIG})
            message(WARNING "Super configuration is not allowed, doc will not generated")
            remove_definitions(GF_DOC)
        endif(${ALLOW_SUPER_CONFIG})        
    endif(${Doxygen_FOUND})
else()
    message(STATUS "Doc will not be generated  as your wish")
    remove_definitions(-DGF_DOC)
endif(${WITH_DOCS})

##end of doc-related stuff

##find cuda package.
find_package(CUDA QUIET)

if(${CUDA_FOUND})
    message(STATUS "Cuda Version: ${CUDA_VERSION}")
    if(${USE_GPU})
        message(STATUS "GPU optimization will be used")
        set(${USE_GPU} ON)
        add_compile_definitions(GF_GPU)
        remove_definitions(GF_CPU)
        if(${USE_CPU})
            message(WARNING "You installed CUDA and specified GPU optimization, 
                    thus CPU computation will be omit")
            unset(${USE_CPU})
        endif(${USE_CPU})        
    else(${USE_GPU})
        message(STATUS "Cuda will not be used since you specified without GPU computation")
        if(${USE_CPU})
            message(STATUS "CPU computation will be adopt")
        else(${USE_CPU})
            message(WARNING "You donot use GPU computation but CPU computation is not specified, 
                    CPU computation will be tacitly used")
            set(${USE_CPU} ON)
        endif(${USE_CPU})
        unset(${USE_CPU})
        add_compile_definitions(GF_CPU)
        remove_definitions(GF_GPU)
    endif(${USE_GPU})
    
else(${CUDA_FOUND})
    message(STATUS "Cannot find cuda")
    unset(${USE_GPU})
    if(${USE_GPU})
        message(WARNING "You specified USE_GPU, but cuda cannot be found")
        message(WARNING "AMD or other devices support will coming soon...")
        unset(${USE_GPU})
    endif(${USE_GPU})

    if(${USE_CPU})
        message(STATUS "CPU computation will be adopt")
    else(${USE_CPU})
        message(WARNING "Cuda not installed, 
            CPU computation will be tacitly used")
        set(${USE_CPU} ON)
    endif(${USE_CPU})
    add_compile_definitions(GF_CPU)
    remove_definitions(GF_GPU)
endif(${CUDA_FOUND})

##end of cuda stuff

if(${CMAKE_HOST_WIN32})
##TODO: you might modify this path if you installed into a different directory.
set(GFLAGS_INCLUDE_DIR "D:/archive/gflags/g_build/include/")
set(GFLAGS_LIBRARY "D:/archive/gflags/g_build/lib")
find_package(gflags REQUIRED)
elseif(${CMAKE_HOST_UNIX})
find_package(gflags QUIET)
if (${gflags_FOUND})
    message(STATUS "GFlags version: ${gflas_VERSION}")
elseif(${USE_CONAN})
    include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ConanGFlags.cmake)
    download_gflags_if_not_exist()
    find_package(gflags REQUIRED)
else()
    ##TODO: add executing process to install gflags in linux system without conan.
endif ()

endif()

find_package(assimp REQUIRED)

add_executable(${PROJECT_NAME} program/main.cpp src/util/CmdParser.cpp src/util/CmdParser.h src/algorithms/FieldType.hpp src/algorithms/Gradient.cpp src/algorithms/Gradient.h src/algorithms/Curl.cpp src/algorithms/Curl.h src/algorithms/Divergence.cpp src/algorithms/Divergence.h src/model_loader/PLYLoader.cpp src/model_loader/PLYLoader.h src/model_loader/OBJLoader.cpp src/model_loader/OBJLoader.h src/model_loader/STLLoader.cpp src/model_loader/STLLoader.h src/operators/PointCloud_Laplacian.cpp src/operators/PointCloud_Laplacian.h src/operators/Affine_Invariant_Laplacian.cpp src/operators/Affine_Invariant_Laplacian.h src/operators/Wave_Kernel_Signature.cpp src/operators/Wave_Kernel_Signature.h src/operators/Anisotropic_Laplacian.cpp src/operators/Anisotropic_Laplacian.h src/operators/Extrinsic_Dirac.cpp src/operators/Extrinsic_Dirac.h)

target_link_libraries(${PROJECT_NAME} ${ASSIMP_LIB})